package satellite

import (
	"time"

	"gddgame.cc/galaxy/utils"
)

type PongSender interface {
	SendPong(bytes []byte)
}

type PingPongClient struct {
	sender PongSender

	ping              uint
	lastPingTimestamp int64
	serverTimestamp   int64
}

func NewPPClient(sender PongSender) *PingPongClient {
	pp := &PingPongClient{
		sender: sender,
	}
	return pp
}

func (pp *PingPongClient) OnPing() {
	pp.lastPingTimestamp = time.Now().Unix()
}

func (pp *PingPongClient) OnPong(message Message) {
	b := message.ReadBytes()
	pp.serverTimestamp = utils.ToInt64(b)
	// 计算ping时间
	if pp.lastPingTimestamp > 0 {
		pp.ping = uint(time.Now().Unix()-pp.lastPingTimestamp) / 2
	}
	pp.sender.SendPong(nil)
}

type PingPongServer struct {
	window int
	sender PongSender

	last       time.Time
	delaySlice []time.Duration
	delay      time.Duration
}

func NewPPServer(window int, sender PongSender) *PingPongServer {
	pp := &PingPongServer{
		sender:     sender,
		window:     window,
		delaySlice: make([]time.Duration, window),
	}
	return pp
}

func (pp *PingPongServer) Delay() (*time.Duration, *time.Time) {
	return &pp.delay, &pp.last
}

func (pp *PingPongServer) OnPing() {
	pp.last = time.Now()
	//c.engine.Debugf("client: %#v send pong", c.sid)
	pp.sender.SendPong(utils.ToBytes(pp.last.UnixNano() / 1e6))
}

func (pp *PingPongServer) OnPong(message Message) {
	if len(pp.delaySlice) >= pp.window {
		pp.delaySlice = pp.delaySlice[1:]
	}
	pp.delaySlice = append(pp.delaySlice, time.Now().Sub(pp.last))
	all := time.Duration(0)
	for i := 0; i < pp.window; i++ {
		all += pp.delaySlice[i]
	}
	pp.delay = all / time.Duration(pp.window)
}
